查看原文
其他

优雅的数据建模方法与实践

数据学堂 数据仓库与Python大数据 2022-11-29

数据模型是数据仓库的核心,数据分析的基础。为确保提供更好的性能、可靠性和准确性,将数据加载到正确设计的模型中是数据仓库、数据分析很重要的一项工作。


1

满足不同需求的不同模式

关于数据建模的一个最重要的经验:没有一个模型可以套用所有的业务需求。然而,我们在面对不同的业务需求时,可以遵循一些最基本的模式对数据进行建模。一般情况下,按建模的规律,我们可以分为三种不同的类型,如下:



当报表要求简单且不复杂时,对一组数据建模的最简单方法有时是将其转换为一个单一的平面表:你可以添加一列值,或者通过其他列进行过滤。在从Excel过渡到Power BI时,使用相同的方法。但这种方法时有一些限制。以下是组织到平面表中的零售订单数据的示例:



如上图,这些数据如果存储在Excel表格中,你可以按“订单日期”列进行筛选,并将数量、单位成本和单价相加。还可以对“公司名称”、“类别”或“产品名称”列应用筛选器。对于简单的报告,这可以满足我们的需要。



2

主/详细模式

通常用于事务数据。主记录(如订单或发票)与明细记录(如订单明细或发票行项目)相关。可以对多个表重复主/详细信息模式,以创建规范化的数据库,但需谨慎使用此模式来获取钻取详细信息。因为在分析数据模型中会包含不必要的细节,且会占用大量内存和存储空间,影响报表性能。



3

维度建模

通过应用维度设计模式:维度规则确实有助于以最佳形式存储描述数据,是以进行报告和分析时的最佳方式。


通过将信息汇总到事实表和维度表中,我们在保持一致性和数据完整性的同时,尽可能存储较少的数据。在模型设计中,我们经常提到“实体”和“属性”。实体是我们追踪的东西(如客户或产品)。实体具有描述特定属性的属性。在数据分析中,实体通常被具体化为维度表,每个属性都是一个列或字段。


事实表包含用于汇总和聚合度量值的数字列,以及与维度表相关的列。维度包含用于对业务事实进行分组和筛选的属性。事实记录在所有维度上共享相同的粒度级别。例如,如果国内销售订单和国际销售订单的客户、产品和订单日期等维度的详细程度相同,则这些记录可以存储在同一事实表中。但是,如果销售目标是在月份级别而不是在日期级别应用的,则它们必须存储在单独的事实表中。


维度模型的本质是星型模式,这里简化为显示一个与维度相关的事实表。



星型模型设计的实际应用如上图所示。“在线销售”事实表包含用于将此表与每个维度关联的关键列。事实表还包含数字类型的列,用于定义聚合和合计数字值(如净价、数量、单位成本、单位折扣和单价)的度量值。你将注意到,从每个维度表到事实表的关系是一对多的,并在一个方向上过滤记录,如关系行上的箭头所示。例如,“客户信息表”与“在线销售”之间的关系基于这两个表中的“客户Key”列。关系筛选方向指示如果在报表上筛选客户表,则会相应地筛选在线销售表。但是,如果在报表中筛选在线销售表,则不会导致筛选客户表。



定义事实表和维度表分为四个阶段:

  • 选择业务流程

  • 确定颗粒度

  • 确定维度

  • 识别事实


是不是看起来很简单呢?接下来,将使用以下步骤分解流程:

  • 将详细的原子数据加载到维度结构中

  • 围绕业务流程构建维度模型

  • 确保每个事实表都有一个关联的日期维度表

  • 确保单个事实表中的所有事实具有相同的粒度或详细程度

  • 解析事实表中的多对多关系

  • 解析维度表中的多对一关系

  • 在维度表中存储报表标签和筛选值

  • 确保维度表使用代理键

  • 创建一致的维度以在整个企业中集成数据

  • 提供DW/BI解决方案

  • 支持业务用户的决策


让我们把这个过程应用到销售订单的平面表中。这里又是一些维度和事实:



上图,有三个单独的日期列记录下订单的日期、到期日期和交付订单的日期。客户信息包括公司名称和可用于查找详细客户信息的唯一“客户Key”。有三个数字列可以汇总或聚合。这些列还可以用于执行更复杂的计算,如比率、运行总计和时间序列比较。


4

维度概念

现在,让我们回顾一些常见的实用维度建模。


1
角色扮演维度

维度实体可以在报告中扮演多个角色。在平面表中,三个日期列有完全不同的用途,但都存储相同类型的值:日期。但是,日期可以用来对数据进行分组和聚合,比如月份、季度、年份或会计期间。它们可用于执行时间序列计算,如上一年的月至今或同期。为此,必须有一个日期维度表,其中包含一段时间内连续的一组日期记录。我们可能需要从过去五年到今年年底的所有日期。日期维度是角色扮演维度中最常见的示例,但在查看更多日期示例之前,让我们先看看另一个场景。


Power BI Desktop包括自动生成日期维度表的功能,还有DAX函数生成日期表。

下图显示了名为“航班”的事实表,其中包含两个角色扮演机场维度。它有一些关于地理位置的信息。在本例中,需要将机场表实现两次:出发机场和到达机场。



有了两个角色扮演机场维度,报表用户可以查询给定日期从日本到澳大利亚的所有航班。


再回到零售销售示例,假设sales事实表有两个日期键:“订单日期” 和“发货日期”。单个日期维度只能有一个活动关系。下图显示了自动检测到的Sales和Date之间的关系的结果,其中一个关系处于非活动状态,事实上对大多数实际用途都啥用处。



此图显示了使用Power Query中的引用查询导入的DATE维度表的三个独立实例。这三个表:“订单日期”、“到期日期” 和“交货日期”比该表的单个实例占用的内存稍多,但为报表用户回答业务问题,提供了更大的灵活性。



每个日期列的表,只有在需要灵活地使用DAX中的时间序列函数或使用日期部分字段(如年、季度或月)执行比较时,才需要单独的日期维度表,否则不需要单独创建日期表。可以使用事实表中的字段来执行诸如计算两个日期类型列之间的差值或计算具有未来日期的行等操作。另外在“视情况而定”的情况,你必须根据业务报告需求做出判断,在简单性和可维护性与复杂性和灵活性之间取得平衡。


2
多对多关系和双向筛选器


许多数据建模决策是性能和功能之间的权衡;使用迭代设计,你通常会找到解决问题的更好方法。有几种不同的方法可以设计多对多关系。传统的方法是使用桥接表,该桥接表包含将两个表关联在一起的所有键组合。在下面的示例中,“客户”和“产品”维度表通常有一个从关系的“一方”到“多方”的单向过滤器。如果报告要求根据购买产品的选定客户筛选产品,我们可以使用“销售”事实表作为桥接表,并将产品和销售之间的关系更改为使用双向筛选器。


根据关系的基数,使用双向过滤器可能会导致性能损失。如果我们只有100种产品,销售记录不到100万,这可能不是什么大事。如果我们有1万种产品和1亿份销售记录,这种关系可能会大大减慢速度(“除非必须这样做,否则不要这样做”)。



下面是另一个示例:鉴于为所选客户帐户和交易记录的要求,下面的模型不适用于现成的关系。要了解原因,请遵循筛选的记录流。从“客户”到“账户客户”,关系行上的箭头指示筛选器流向正确的方向。一旦“客户”表被过滤,“账户表”将不被过滤,因为关系不会自然地从多侧流向单侧。



将关系筛选器更改为“双向”可修复问题并满足报告要求。



如前所述,双向滤波器引入了潜在的性能损失。但是,如果基数很低,数据模型的内存占用也很小(使用有效的键值并删除不必要的列),那么这种设计可能会执行得很好。




数仓之路      学习路线

面试系列      大佬访谈


点击上面文字即可跳转专题


还想看更多?

戳下面查看更多干货👇




♤数仓深度 | 数据脱敏方式与应用

♤大数据ETL工具 Kettle 入门实践


☆数仓深度 | 主数据管理

数仓深度 | 数据生命周期管理

数仓深度 | 浅谈数据资产盘点

数仓深度 | 数据治理之数据脱敏

数仓深度 | 实时数仓之架构对比

数仓深度|数据模型如何论好坏

数仓深度 | 传统数仓和大数据数仓的区别

数仓深度 | OneData指标标准化管理实践




扩展阅读:公众号后台回复“数仓”,转发即可下载视频资料。

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存